﻿using System;
using System.Globalization;

namespace Microsoft.International.Formatters
{

    /// <summary>
    /// French (fr-BE and fr-CH) formatter
    /// </summary>
    [FormatCultureInfoAttribute("fr-BE")]
    [FormatCultureInfoAttribute("fr-CH")]
    internal sealed class FRBeChStdFormatter : EuropeFormatter
    {

        /// <summary>
        /// Returns the Decimal value to String.
        /// </summary>
        /// <param name="num">Value to translate.</param>
        /// <returns>Returns the specified Decimal value to String.</returns>
        /// <remarks>Abstract method, must be implemented.</remarks>
        internal override String ConvertToLocalizedText(Decimal num)
        {
            String strMoins = String.Empty;
            Int32 value = (Int32)num;
            if (value < 0)
            {
                strMoins = "moins ";
                if (value == Int32.MinValue)
                {
                    strMoins += "deux milliards ";
                    value += 2000000000;
                }
                value = Math.Abs(value);
            }

            return strMoins + BillionToString(value);
        }

        /// <summary>
        /// Convert units (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String UnitToString(Int32 value)
        {
            if (value > 9)
                return TenToString(value);

            String result = String.Empty;

            switch (value.ToString(new CultureInfo("fr-FR")))
            {
                case "0": result = "zéro"; break;
                case "1": result = "un"; break;
                case "2": result = "deux"; break;
                case "3": result = "trois"; break;
                case "4": result = "quatre"; break;
                case "5": result = "cinq"; break;
                case "6": result = "six"; break;
                case "7": result = "sept"; break;
                case "8": result = "huit"; break;
                case "9": result = "neuf"; break;
            }

            return result;
        }

        /// <summary>
        /// Convert tens (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String TenToString(Int32 value)
        {
            if (value < 10)
                return UnitToString(value);
            else if (value > 99)
                return HundredToString(value);

            String result = String.Empty;

            switch (value)
            {
                case 10: result = "dix"; break;
                case 11: result = "onze"; break;
                case 12: result = "douze"; break;
                case 13: result = "treize"; break;
                case 14: result = "quatorze"; break;
                case 15: result = "quinze"; break;
                case 16: result = "seize"; break;
                case 20: result = "vingt"; break;
                case 21: result = "vingt et un"; break;
                case 30: result = "trente"; break;
                case 31: result = "trente et un"; break;
                case 40: result = "quarante"; break;
                case 41: result = "quarante et un"; break;
                case 50: result = "cinquante"; break;
                case 51: result = "cinquante et un"; break;
                case 60: result = "soixante"; break;
                case 61: result = "soixante et un"; break;
                case 70: result = "septante"; break;
                case 71: result = "septante et un"; break;
                case 80: result = "quatre-vingts"; break;
                case 90: result = "nonante"; break;
                case 91: result = "nonante et un"; break;
                default:
                    if (value.Between(72, 79))
                        result = String.Format(new CultureInfo("fr-BE"), "septante-{0}", UnitToString(value - 70));
                    else if (value.Between(92, 99))
                        result = String.Format(new CultureInfo("fr-BE"), "nonante-{0}", UnitToString(value - 90));
                    else if (value.Between(81, 89))
                        result = String.Format(new CultureInfo("fr-BE"), "quatre-vingt-{0}", UnitToString(value.GetUnit()));
                    else
                        result = String.Format(new CultureInfo("fr-BE"), "{0}-{1}", TenToString(value.GetTen()), UnitToString(value.GetUnit()));
                    break;
            }

            return result;
        }

        /// <summary>
        /// Convert hundreds (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String HundredToString(Int32 value)
        {
            if (value < 100)
                return TenToString(value);
            else if (value > 999)
                return ThousandToString(value);

            if (value == 100) return "cent";

            Int32 reste = 0;
            Int32 centaine = System.Math.DivRem(value, 100, out reste);

            String strCentaine = "cent";
            if (centaine != 1) strCentaine = String.Format(new CultureInfo("fr-BE"), "{0} cent", TenToString(centaine));

            if (reste == 0)
                return String.Format(new CultureInfo("fr-BE"), "{0}s", strCentaine);
            else
                return String.Format(new CultureInfo("fr-BE"), "{0} {1}", strCentaine, TenToString(reste));

        }

        /// <summary>
        /// Convert thousands (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String ThousandToString(Int32 value)
        {
            if (value < 1000)
                return HundredToString(value);
            else if (value > 999999)
                return MillionToString(value);

            if (value == 1000) return "mille";

            Int32 reste = 0;
            Int32 millier = System.Math.DivRem(value, 1000, out reste);

            String strMillier = "mille";

            if (millier != 1) strMillier = String.Format(new CultureInfo("fr-BE"), "{0} mille", HundredToString(millier).Replace("cents", "cent"));

            if (reste == 0) return strMillier;
            return String.Format(new CultureInfo("fr-FR"), "{0} {1}", strMillier, HundredToString(reste));
        }

        /// <summary>
        /// Convert millions (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String MillionToString(Int32 value)
        {
            if (value < 1000000)
                return HundredToString(value);
            else if (value > 999999999)
                return BillionToString(value);

            if (value == 1000000) return "un million";

            Int32 reste = 0;
            Int32 millions = System.Math.DivRem(value, 1000000, out reste);

            String s = (millions > 1 ? "s" : "");
            String strMillions = String.Format(new CultureInfo("fr-BE"), "{0} million{1}", HundredToString(millions), s);

            return String.Format(new CultureInfo("fr-BE"), "{0} {1}", strMillions, ThousandToString(reste));
        }

        /// <summary>
        /// Convert billions (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String BillionToString(Int32 value)
        {
            if (value < 1000000000)
                return MillionToString(value);

            if (value == 1000000000) return "un milliard";

            Int32 reste = 0;
            Int32 milliard = System.Math.DivRem(value, 1000000000, out reste);

            String s = (milliard > 1 ? "s" : "");
            String strMilliard = String.Format(new CultureInfo("fr-BE"), "{0} milliard{1}", HundredToString(milliard), s);

            return String.Format(new CultureInfo("fr-BE"), "{0} {1}", strMilliard, ThousandToString(reste));
        }

    }

}